#include "ServerOp.h"
#include"xsec.h"
#include<unistd.h>
#include <cstring> 
#include<fstream>
void ServerOp::getRandString(int len,char*randBuf)
{
int flag = -1;
	// 靠靠靠
	srand(time(NULL));
	// 靠靠�: A-Z, a-z, 0-9, 靠靠(!@#$%^&*()_+=)
	char chars[] = "!@#$%^&*()_+=";
	for (int i = 0; i < len-1; ++i)
	{
		flag = rand() % 4;
		switch (flag)
		{
		case 0:
			randBuf[i] = rand() % 26 + 'A';
			break;
		case 1:
			randBuf[i] = rand() % 26 + 'a';
			break;
		case 2:
			randBuf[i] = rand() % 10 + '0';
			break;
		case 3:
			randBuf[i] = chars[rand() % strlen(chars)];
			break;
		default:
			break;
		}
	}
	randBuf[len - 1] = '\0';		
}
void ServerOp::startwork()
{
	cout<<"listen" <<endl;
	server_.setListen(8888);
	TcpSocket*sock=server_.acceptConn(3);
	if (sock == nullptr)
	{
		cout << "accept error" << endl;
		return;
	}
	cout << "client connect to server success!" << endl;
	////////////////////////////////建立连接后拿到client 的证书/////////////////////////////
	
	char *buf=NULL;
	int bufsize=-1;
	sock->recvMsg(&buf,bufsize);
	  
	 //对方的证书存在buf中，将证书写入磁盘
	 ofstream ofs("client.crt",ios::binary);
	 if(!ofs)
		{
			cout<<"ofstream failed!"<<endl;
			return;
		}
	  ofs.write(buf,bufsize);
		ofs.close();
	
	////////////////////////////////server开始将自己的证书发送给client/////////////////
	char mycrtbuf[4096]={0};
	ifstream ifs("server.crt",ios::binary);
		if(!ifs)
			{
         return;
         cout<<"open file error!"<<endl;
			}
	ifs.read(mycrtbuf,sizeof(mycrtbuf));
	int readn=ifs.gcount();
	
	sock->sendMsg(mycrtbuf,readn);
	ifs.close();
	
	////////////////////至此客户端和服务器都拿到了对方的证书////////////////////////////////////
	
	/////////拿到数据////////
	char* recvBuf = nullptr;
	int recvBuflen = 0;
	sock->recvMsg(&recvBuf,recvBuflen);


	/////////DER解密///////////////
	CodecFactory * factory = new RequestFactory;
	Codec *codec = factory->createCodec();
	RequestMsg*reqMsg = (RequestMsg*)codec->msgDecode(recvBuf, recvBuflen);


	
	char *outdata = nullptr;
	int outlen = 0;
	seckeyAgree(reqMsg, &outdata, outlen);
	//outdata里面的数据已经序列化

	sock->sendMsg(outdata,outlen);
	
	getchar();
	delete factory;
	delete sock;
}

int ServerOp::seckeyAgree(RequestMsg * reqMsg, char ** outData, int & outLen)
{
	RespondMsg resMsg;
	
	//开始解密r1中的内容
	XSEC sec("client.crt","server.key");
	int r1len=strlen(reqMsg->r1);
	unsigned char keytmp[1024] ={0};
	sec.DeCrypto((unsigned char*)reqMsg->r1,r1len,keytmp); //r1的明文数据放在keytmp中

	
	/////////////验证r1有没有被篡改过/////////////////////
	char keyhmac[1024] = { 0 };
	unsigned int mdlen = -1;
	unsigned char mdHmac[SHA256_DIGEST_LENGTH];
	sprintf(keyhmac, "@%s+%s@", "1001", reqMsg->clientId);
	HMAC(EVP_sha256(), keyhmac, strlen(keyhmac), (const unsigned char*)keytmp, strlen((char*)keytmp), mdHmac, &mdlen);
	for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
	{
		sprintf(&keyhmac[i * 2], "%02x", mdHmac[i]);
	}
	if (strcmp(keyhmac, reqMsg->authCode) != 0)
	{
		cout << "hmac error" << endl;
		return -1;
	}
	cout << "hman suceess!" << endl;
	
	char r2tmp[6]={0};
	getRandString(sizeof(r2tmp),r2tmp);
	// 1.1 生成秘钥
	char key[1024] = { 0 };
	unsigned char mdSha[SHA_DIGEST_LENGTH];
	sprintf(key, "%s%s", keytmp, r2tmp);
	SHA1((unsigned char*)key, strlen(key), (unsigned char*)mdSha);
	for (int i = 0; i < SHA_DIGEST_LENGTH; ++i)
	{
		sprintf(&key[i * 2], "%02x", mdSha[i]);
	}
	cout << "seckey: " << key << endl;

   
	//组织给客户端的信息
	resMsg.rv = 0;
	resMsg.seckeyid = 0001;
	strcpy(resMsg.clientId, reqMsg->clientId);
	strcpy(resMsg.serverId, "1001");


	//对resmsg.r2加密
	int r2tmplen=sizeof(r2tmp);
	sec.EnCrypto((unsigned char*)r2tmp,r2tmplen,(unsigned char*)resMsg.r2);
	//序列化发送
	CodecFactory* factory = new RespondFactory(&resMsg);
	Codec* codec = factory->createCodec();
	codec->msgEncode(outData, outLen);
		//密钥写入数据库，写入共享内存
	NodeSHMInfo node;
	memset(&node,0x00,sizeof(NodeSHMInfo));
	node.status=0;
	strcpy(node.serverID,"1001");
	strcpy(node.clientID,"1002");
	strcpy(node.seckey,key);
	node.seckeyID=resMsg.seckeyid;
	shm_->shmWrite(&node);
	return 0;
}


